home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’93
/
Windoid
/
InfinityWindoid.c
< prev
next >
Wrap
Text File
|
1993-06-18
|
41KB
|
1,278 lines
/******************************************************************************
NAME:
Infinity Windoid 2.3
FILE:
InfinityWindoid.c
WRITTEN BY:
Troy Gaul
Infinity Systems
© 1991-93 Infinity Systems
All rights reserved.
DESCRIPTION:
This file contains the source for a standalone code resource that
conforms to a Window DEFinition (WDEF), as defined by Apple Computer
in Inside Macintosh.
It provides a 'windoid' appearance. A windoid is a floating window
that appears above document windows in an application and is commonly
used for things like tool palettes, information windows, and the like.
The WDEF included in the ResEdit file can be used as-is, but if a zoom
box is to be used, you will probably want to change the behavior of
what is included (by default, it zooms smaller rather than larger as
described below). This WDEF is created for System 6 and later, but it
would be easy to modify it for earlier systems if this is important.
FEATURES:
• Supports System 7-style coloring of windows.
• In System 7, the tinge color set by the user in the Color control
panel is used.
• Close box can be enabled from NewWindow by setting goAwayFlag.
• Zoom box (special case) implemented, utilized by adding zoomDocProc
to the proc ID used to create the windoid.
• Title bar can appear along the left of the window if 1 is added to
the proc ID (with or without a zoom box).
• For MacApp users, the left/top behavior of the proc ID can be
switched.
• System 6 coloring scheme is also supported (can be set in Kolor or
a similar control panel).
• In System 7, DeviceLoop is used so the windoid will be drawn
correctly even when it crosses monitors of differing depths.
• In System 7, indexed color tables are checked to see if there are
enough different colors to display the color version (like the
system WDEF).
-------------------------------------------------------------------------------
HOW TO CONTACT THE AUTHOR:
Troy Gaul
Infinity Systems
MicroFrontier, Inc.
3401 101st Street
Suite E
Des Moines, IA 50322
(515) 270-8109
Internet: t-gaul@grayhawk.rent.com
AppleLink: mfrontier
America Online: ntwing
mfrontier
FAX: (515) 278-6828
******************************************************************************/
//*****************************************************************************
// Include files
//-----------------------------------------------------------------------------
#define SystemSixOrLater 1
// This is used so that we can cut down on the code size in MPW. If you
// think support for earlier systems is important, get rid of this.
// Note: for this define to work under THINK C, MacHeaders should NOT
// be included.
//-----------------------------------------------------------------------------
#include <Memory.h>
#include <QuickDraw.h>
#include <OSUtils.h>
#include <Windows.h>
#include <Palettes.h>
#include <ToolUtils.h>
#include <Desk.h>
/******************************************************************************
// Conditional Compilation Options
//-----------------------------------------------------------------------------
The #define's you may make include:
ALLOW_ZOOM - This option creates a windoid that supports a zoombox.
To add the zoombox to a windoid, add zoomDocProc to the
procID when creating the window. The application is
responsible for setting the user state and standard state
Rects of the window for zooming. (When a new window is
created, both of these are initialized to the bounds
of the window. See the README for more information).
STAYPUT_ZOOM - This option will cause both the user and standard Rects to
be changed together, causing the zoomed in and out state
to have the same topLeft at all times. If this is not set,
the standard and user states have their own 'memories'.
(Note: this behavior is not fully tested.)
MFI_ZOOM - This will cause the WDEF to handle the zoom box in the way
expected by MicroFrontier applications (the same way as
version 2.2). That is, the other state that is used is one
which has a title bar with a small area (in which the host
program displays a label for the windoid).
ALLOW_VERT - This determines if the code that is compiled will support
a palette that has a vertical title bar along the left
side of the window (rather than the top). To create such
a window, add one to the varcode that is used.
MACAPP_STYLE - This determines if the varcodes that are supported are
the one's I consider 'normal' or the ones MacApp's
windoid WDEF knows about. Note, however, that this code
only supports the 'smaller', title-less version that
is available in MacApp's.
THINK_STYLE - This creates a version of the WDEF that is totally
compatible with the varcodes used in the windoid WDEF
included with the THINK environments. Two things are done:
varcode 0 gives a normal titlebar, varcode 2 gives a
titlebar down the left side, and other varcodes (i.e.
1,3,4,5,6,7) give no titlebar at all. (Note that in my
version, a zoom box may also be used with this style.)
Also, for the THINK style, ALWAYS_HILITE is also set, as
this is how theirs works.
ALWAYS_HILITE - This will cause a windoid to be created that will always
draw its title bar with gadgets and all. Normally, the
windoid will draw the titlebar and frame in gray and
empty when the window is not hilighted (like normal
windows). Some programs, however, don't keep their
windoids properly hilighted, so this will make them
appear to always be active.
VERS_2_2_COMPATIBLE - This creates a version of the WDEF that is
functionally compatible with the version 2.2 windoid that
I released. The only issue involved is the way the zooming
is handled.
-----------------------------------------------------------------------------*/
#define ALLOW_ZOOM
#define ALLOW_VERT
#define VERS_2_2_COMPATIBLE
//-----------------------------------------------------------------------------
#ifdef VERS_2_2_COMPATIBLE
#ifndef MFI_ZOOM
#define MFI_ZOOM
#endif
#ifndef STAYPUT_ZOOM
#define STAYPUT_ZOOM
#endif
#endif
//-----------------------------------------------------------------------------
#ifdef THINK_STYLE
#ifndef ALLOW_VERT
#define ALLOW_VERT
#endif
#ifndef ALWAYS_HILITE
#define ALWAYS_HILITE
#endif
#ifdef MACAPP_STYLE
#undef MACAPP_STYLE
#endif
#endif
//-----------------------------------------------------------------------------
#ifdef MACAPP_STYLE
#ifdef ALLOW_VERT
#undef ALLOW_VERT
#endif
#ifdef ALWAYS_HILITE
#undef ALWAYS_HILITE
#endif
#endif
//*****************************************************************************
// Constants
//-----------------------------------------------------------------------------
#define kTitleHeight 11
// This is the height of the windoid's titlebar.
#define kGadgetInset 2
// inset from top/bottom of titlebar (with titlebar on top of window)
#define kGadgetMargin 6
// space between edge and gadget
#define kGadgetSize (kTitleHeight - (2 * kGadgetInset))
//-----------------------------------------------------------------------------
// Color table tinge percentage constants
//-----------------------------------------------------------------------------
#define wTitleBarLightPct 0x1
#define wTitleBarDarkPct 0x8
#define wCloseBoxColor 0x5
#define wXedBoxPct 0x8
#define wInactiveFramePct 0xA
//-----------------------------------------------------------------------------
// Color table constants
//-----------------------------------------------------------------------------
enum {
wHiliteColorLight = 5,
wHiliteColorDark,
wTitleBarLight,
wTitleBarDark,
wDialogLight,
wDialogDark,
wTingeLight,
wTingeDark
};
// These are the constants defined in the Apple technical note regarding
// Color, Windows, and System 7. Last I checked, they weren't in an Apple
// header file. (But the ones < 5 are, from the previous, pre-System 7
// coloring scheme.)
//-----------------------------------------------------------------------------
// Style variation constants
//-----------------------------------------------------------------------------
enum {
blackandwhite = 0,
sys7color,
sys6color
};
// These constants represent the three types of window 'colorings' we
// support.
//-----------------------------------------------------------------------------
// MacApp style variations
//-----------------------------------------------------------------------------
#define kMacApp_toggleTBar 0x1 // bit 0 tells us whether to hilite/unhilite title bar
#define kMacApp_hasTallTBar 0x2 // bit 1 is tall title bar bit (unsupported)
#define kMacApp_hasGrow 0x4 // bit 2 is grow bit (std grow bit, unsupported)
#define kMacApp_hasZoom 0x8 // bit 3 is zoom bit (standard zoom bit)
//*****************************************************************************
// Structures
//-----------------------------------------------------------------------------
typedef struct WindoidData {
WStateData wState;
unsigned int closeToggle : 1;
unsigned int zoomToggle : 1;
unsigned int isSystem7 : 1;
unsigned int hasCQD : 1;
unsigned int isHoriz : 1;
unsigned int ignoreHilite : 1;
unsigned int hasTitlebar : 1;
} WindoidData, **WindoidDataHandle;
#define WindData (**(WindoidDataHandle)(window->dataHandle))
// This macro is used so I can access the 'globals' easily. Note: the
// variable containing the window must be 'window', and it must be in
// scope at the time of the usage of this macro.
// Also, they aren't REALLY globals, becuase they're kept for EACH window,
// which is why I use a bitfield, trying to keep this as small as
// possible.)
//*****************************************************************************
// Function Prototypes
//-----------------------------------------------------------------------------
void DoWInit(WindowPeek window, long param, short varCode);
void DoWDispose(WindowPeek window, long param);
long DoWHit(WindowPeek window, long param);
void DoWDraw(WindowPeek window, long param);
void DoWCalcRgns(WindowPeek window, long param);
void DoWGrow(WindowPeek window, long param);
void DoWDrawGIcon(WindowPeek window, long param);
void SyncPorts(void);
//*****************************************************************************
// Windoid Main Function
//-----------------------------------------------------------------------------
// This is the main entry point for all calls to this code resource. It
// dispatches to routines that correspond to the message it is given.
//-----------------------------------------------------------------------------
pascal long main( short varCode, WindowPeek window,
short message, long param ) {
GrafPtr savePort;
long result;
Boolean isADrawMsg;
// This sets up the appropriate drawing environment, but only for those
// messages for which we actually need to draw.
isADrawMsg = (message == wDraw || message == wHit || message == wDrawGIcon);
if (isADrawMsg && WindData.hasCQD) {
GetPort(&savePort);
SyncPorts();
}
switch (message) {
case wNew: DoWInit(window, param, varCode);
break;
case wDispose: DoWDispose(window, param);
break;
case wDraw: DoWDraw(window, param & 0xFFFF);
break;
// There's a tech note that says that for the draw message, only
// the low-order word of param is set correctly, so we should do
// this (AND with 0xFFFF) to be sure we're looking at the correct value.
case wHit: result = DoWHit(window, param);
break;
case wCalcRgns: DoWCalcRgns(window, param);
break;
case wGrow: DoWGrow(window, param);
break;
case wDrawGIcon: DoWDrawGIcon(window, param);
break;
}
if (isADrawMsg)
SetPort(savePort);
return result;
}
//*****************************************************************************
// Environment-determining Routines
//-----------------------------------------------------------------------------
// These use SysEnvirons so we don't have to rely on Gestalt being available
// and so MPW won't include that code in our resource.
short HasSystem7( void ) {
SysEnvRec theWorld;
long theSysVers;
if (SysEnvirons(1, &theWorld) == noErr) {
theSysVers = (long)theWorld.systemVersion;
return (theSysVers >= 0x0700);
} else
return false;
}
//-----------------------------------------------------------------------------
short HasCQDraw( void ) {
SysEnvRec theWorld;
if ((SysEnvirons(1, &theWorld) == noErr) && theWorld.hasColorQD)
return 1;
else
return 0;
}
//*****************************************************************************
// SyncPorts
//-----------------------------------------------------------------------------
// Straight from the pages of _Macintosh Programming Secrets_, Second
// Edition by Scott Knaster and Keith Rollin (page 425). (except that this
// version doesn't check Gestalt, it will only be called if CQD is running)
// This routines was added to 2.3. It makes sure the drawing environment
// is set correctly if the system has color. This is not needed for the
// code in this WDEF as it is, but if a DoWDrawGIcon handler is implemented,
// this is needed to make sure the drawing environment is set as Apple
// tells us it will be for drawing the gray, xor'ed border.
void SyncPorts( void ) {
GrafPtr bwPort;
CGrafPtr colorPort;
GetWMgrPort(&bwPort);
GetCWMgrPort(&colorPort);
SetPort((GrafPtr)colorPort);
BlockMove(&bwPort->pnLoc, &colorPort->pnLoc, 10);
BlockMove(&bwPort->pnVis, &colorPort->pnVis, 14);
PenPat((ConstPatternParam)&bwPort->pnPat);
BackPat((ConstPatternParam)&bwPort->bkPat);
}
//*****************************************************************************
// Color Mixing Routines
//-----------------------------------------------------------------------------
void GetWctbColor( WindowPeek window, short partCode, RGBColor *theColor ) {
// Given a partCode, return the RGBColor associated with it. (Using the
// default window color table.)
AuxWinHandle awHndl;
short junkResult;
junkResult = GetAuxWin((WindowPtr)window, &awHndl);
*theColor = (**(WCTabHandle)((**awHndl).awCTable)).ctTable[partCode].rgb;
}
//-----------------------------------------------------------------------------
void SetWctbColor( WindowPeek window, short partCode ) {
RGBColor theColor;
GetWctbColor(window, partCode, &theColor);
RGBForeColor(&theColor);
}
//-----------------------------------------------------------------------------
#pragma processor 68020
// Note: this should be okay because this will only be called if we are
// doing System 7 color, which requires Color Quickdraw, which is only
// available on systems with 68020's or better. Again, this is done to
// reduce code size. If it isn't compiled this way, several routines will
// be added to handle the long integer arithmetic. We would like to avoid
// that.
void MixColor( const RGBColor *lightColor, const RGBColor *darkColor,
short shade, RGBColor *result ) {
shade = 0x0F - shade;
// This is necessary because we give shades between light and
// dark (0% is light), but for colors, $0000 is black and $FFFF
// is dark.
result->red = ((lightColor->red - darkColor->red) * shade / 15)
+ darkColor->red;
result->green = ((lightColor->green - darkColor->green) * shade / 15)
+ darkColor->green;
result->blue = ((lightColor->blue - darkColor->blue) * shade / 15)
+ darkColor->blue;
}
#pragma processor 68000
//-----------------------------------------------------------------------------
void AvgWctbColor( WindowPeek window, short light, short dark, short shade,
RGBColor *theColor ) {
// Mix two parts by the given shade, which is actually a value
// between 0 (0%) and 15 (100%), return the RGBColor.
RGBColor lightColor;
RGBColor darkColor;
GetWctbColor(window, light, &lightColor);
GetWctbColor(window, dark, &darkColor);
MixColor(&lightColor, &darkColor, shade, theColor);
}
//*****************************************************************************
// Helper Functions
//-----------------------------------------------------------------------------
void FrameBox( const Rect *theRect ) {
Rect tempRect = *theRect;
FrameRect(theRect);
InsetRect(&tempRect, 1, 1);
EraseRect(&tempRect);
}
//-----------------------------------------------------------------------------
void GetGlobalContentRect( WindowPeek window, Rect *contentRect ) {
GrafPtr savePort;
GetPort(&savePort);
SetPort((GrafPtr)window);
*contentRect = window->port.portRect;
LocalToGlobal((Point*)&contentRect->top);
LocalToGlobal((Point*)&contentRect->bottom);
SetPort(savePort);
}
//*****************************************************************************
// Routines to get Rects for title bar parts
//-----------------------------------------------------------------------------
void GetTitleBar( WindowPeek window, Rect *titleBar ) {
*titleBar = (**(window->strucRgn)).rgnBBox;
if (WindData.isHoriz) {
// title bar on top
titleBar->bottom = titleBar->top + kTitleHeight;
titleBar->right -= 1; // shadow compensation
} else {
// title bar on left
titleBar->right = titleBar->left + kTitleHeight;
titleBar->bottom -= 1; // shadow compensation
}
}
//-----------------------------------------------------------------------------
void GetCloseBox( WindowPeek window, const Rect *titleRect, Rect *theRect ) {
#pragma unused(window)
*theRect = *titleRect;
if (WindData.isHoriz)
InsetRect(theRect, kGadgetMargin, kGadgetInset); // titlebar on top
else
InsetRect(theRect, kGadgetInset, kGadgetMargin); // titlebar on left
theRect->bottom = theRect->top + kGadgetSize;
theRect->right = theRect->left + kGadgetSize;
}
//-----------------------------------------------------------------------------
#ifdef ALLOW_ZOOM
void GetZoomBox( WindowPeek window, const Rect *titleRect, Rect *theRect ) {
#pragma unused(window)
*theRect = *titleRect;
if (WindData.isHoriz)
InsetRect(theRect, kGadgetMargin, kGadgetInset); // titlebar on top
else
InsetRect(theRect, kGadgetInset, kGadgetMargin); // titlebar on left
theRect->top = theRect->bottom - kGadgetSize;
theRect->left = theRect->right - kGadgetSize;
}
#endif
//*****************************************************************************
// Zoom handling
//-----------------------------------------------------------------------------
#ifdef ALLOW_ZOOM
void SetZoomRects( WindowPeek window ) {
Rect contRect;
if (window->spareFlag) {
GetGlobalContentRect(window, &contRect);
WindData.wState.stdState = contRect;
#ifdef MFI_ZOOM
if (WindData.isHoriz) // titlebar on top
contRect.bottom = contRect.top + 12;
else // titlebar on left
contRect.right = contRect.left + 12;
#endif
WindData.wState.userState = contRect;
// the stdState and user state might be backwards from how they
// would normally be used by an application. Check this for your
// own use and change them if necessary.
}
}
//-----------------------------------------------------------------------------
long GetZoomHitType( WindowPeek window ) {
Rect contRect;
Rect stdRect;
contRect = (**(window->contRgn)).rgnBBox;
stdRect = WindData.wState.stdState;
OffsetRect(&stdRect, -stdRect.left + contRect.left,
-stdRect.top + contRect.top);
// make topLeft the same for content and standard rects, and compare
if (EqualRect(&contRect, &stdRect))
return wInZoomIn; // go to user state (make small, MFI)
else
return wInZoomOut; // go to standard state (make normal, MFI)
}
#endif
//*****************************************************************************
// DoWInit -- Windoid initialization
//-----------------------------------------------------------------------------
void DoWInit( WindowPeek window, long param, short varCode ) {
#pragma unused(param)
Handle zoomStuff;
window->spareFlag = false;
zoomStuff = NewHandle(sizeof(WindoidData));
if (zoomStuff) {
window->dataHandle = zoomStuff;
WindData.closeToggle = 0;
WindData.hasCQD = HasCQDraw();
WindData.isSystem7 = HasSystem7();
WindData.hasTitlebar = true;
WindData.ignoreHilite = false;
#ifdef ALLOW_VERT
WindData.isHoriz = (((varCode & 1) == 0) && ((varCode & 2) == 0));
#else
WindData.isHoriz = true;
#endif
#ifdef ALLOW_ZOOM
WindData.zoomToggle = 0;
window->spareFlag = ((zoomDocProc & varCode) != 0);
SetZoomRects(window);
#endif
#ifdef ALWAYS_HILITE
WindData.ignoreHilite = true;
#endif
#ifdef MACAPP_STYLE
WindData.ignoreHilite = !((kMacApp_toggleTBar & varCode) != 0);
#endif
#ifdef THINK_STYLE
if (((varCode & 7) != 0) && ((varCode & 7) != 2))
WindData.hasTitlebar = false;
#endif
}
}
//*****************************************************************************
// DoWDispose -- Windoid disposal
//-----------------------------------------------------------------------------
void DoWDispose( WindowPeek window, long param ) {
#pragma unused(param)
if (window->dataHandle)
DisposeHandle(window->dataHandle);
}
//*****************************************************************************
// DoWHit -- Windoid hit routine
//-----------------------------------------------------------------------------
long DoWHit( WindowPeek window, long param ) {
Rect stdRect;
Rect usrRect;
Rect titleRect;
Rect contentRect;
Rect theRect;
Point hitPt;
long result;
hitPt.v = HiWord(param);
hitPt.h = LoWord(param);
result = wNoHit;
if (PtInRgn(hitPt, window->contRgn))
result = wInContent;
else {
GetTitleBar(window, &titleRect);
if (WindData.hasTitlebar && PtInRect(hitPt, &titleRect)) {
result = wInDrag;
if (WindData.ignoreHilite || window->hilited) {
if (window->goAwayFlag) {
GetCloseBox(window, &titleRect, &theRect);
if (PtInRect(hitPt, &theRect))
result = wInGoAway;
}
#ifdef ALLOW_ZOOM
if (window->spareFlag) {
GetZoomBox(window, &titleRect, &theRect);
if (PtInRect(hitPt, &theRect)) {
result = GetZoomHitType(window);
// Calculate Offset for Zoom Rects (make sure they
// are up to date)
contentRect = (**(window->contRgn)).rgnBBox;
stdRect = WindData.wState.stdState;
usrRect = WindData.wState.userState;
#ifdef STAYPUT_ZOOM
OffsetRect(&(WindData.wState.stdState),
contentRect.left - stdRect.left,
contentRect.top - stdRect.top);
OffsetRect(&(WindData.wState.userState),
contentRect.left - usrRect.left,
contentRect.top - usrRect.top);
#else
if (result == wInZoomIn) {
OffsetRect(&(WindData.wState.stdState),
contentRect.left - stdRect.left,
contentRect.top - stdRect.top);
} else {
OffsetRect(&(WindData.wState.userState),
contentRect.left - usrRect.left,
contentRect.top - usrRect.top);
}
#endif
}
}
#endif
}
}
}
return result;
}
//*****************************************************************************
// DoWDraw -- Windoid drawing routines
//-----------------------------------------------------------------------------
void DrawCloseBox( WindowPeek window, short variation, Rect *theRect ) {
RGBColor theColor;
Rect tempRect;
switch (variation) {
case blackandwhite:
FrameBox(theRect);
break;
case sys6color:
SetWctbColor(window, wHiliteColor);
GetWctbColor(window, wTitleBarColor, &theColor);
RGBBackColor(&theColor);
FrameBox(theRect);
break;
case sys7color:
SetWctbColor(window, wTingeLight);
tempRect = *theRect;
tempRect.top++;
tempRect.left++;
FrameRect(&tempRect);
SetWctbColor(window, wTingeDark);
MoveTo(theRect->right - 1, theRect->top);
LineTo(theRect->left, theRect->top);
LineTo(theRect->left, theRect->bottom - 1);
MoveTo(theRect->right - 2, theRect->top + 2);
LineTo(theRect->right - 2, theRect->bottom - 2);
LineTo(theRect->left + 2, theRect->bottom - 2);
AvgWctbColor(window, wHiliteColorLight, wHiliteColorDark,
wCloseBoxColor, &theColor);
RGBForeColor(&theColor);
tempRect = *theRect;
InsetRect(&tempRect, 2, 2);
PaintRect(&tempRect);
break;
}
}
//*****************************************************************************
// DrawZoomBox -- Draw zoom box
//-----------------------------------------------------------------------------
#ifdef ALLOW_ZOOM
void DrawZoomBox( WindowPeek window, short variation, Rect *theRect ) {
Rect tempRect;
RGBColor theColor;
switch (variation) {
case blackandwhite:
case sys6color:
if (variation != blackandwhite) {
SetWctbColor(window, wHiliteColor);
GetWctbColor(window, wTitleBarColor, &theColor);
RGBBackColor(&theColor);
}
FrameBox(theRect);
tempRect = *theRect;
tempRect.bottom -= 3;
tempRect.right -= 3;
FrameRect(&tempRect);
break;
case sys7color:
DrawCloseBox(window, variation, theRect);
SetWctbColor(window, wTingeDark);
MoveTo(theRect->right - 4, theRect->top + 2);
LineTo(theRect->right - 4, theRect->bottom - 4);
LineTo(theRect->left + 2, theRect->bottom - 4);
break;
}
}
#endif
//*****************************************************************************
// DrawXedBox -- Draw close or zoom box with an X in it (or inverted in B&W)
//-----------------------------------------------------------------------------
void DrawXedBox( WindowPeek window, short variation, Rect *theRect ) {
RGBColor theColor;
switch (variation) {
case blackandwhite:
PaintRect(theRect);
break;
case sys6color:
SetWctbColor(window, wHiliteColor);
PaintRect(theRect);
break;
case sys7color:
AvgWctbColor(window, wTingeLight, wTingeDark, wXedBoxPct, &theColor);
RGBForeColor(&theColor);
PaintRect(theRect);
SetWctbColor(window, wFrameColor);
FrameRect(theRect);
MoveTo(theRect->left, theRect->top); // Draw the 'X'
LineTo(theRect->right - 1, theRect->bottom - 1);
MoveTo(theRect->right - 1, theRect->top);
LineTo(theRect->left, theRect->bottom - 1);
break;
}
}
//*****************************************************************************
// DrawTitlePat -- Draw pattern into the title bar
//-----------------------------------------------------------------------------
// This routine actually draws the pattern into the titlebar. Note: it
// takes a Rect as a parameter (not by address) because it goes ahead and
// modifies it. I figured this was no worse than needing to copy it into
// a local variable, so I went ahead and did it this way.
void DrawTitlePatPat( WindowPeek window, Rect titleRect ) {
#pragma unused (window)
Pattern titlePat;
long patternSeed;
Point corner;
Rect tempRect;
RgnHandle titleRgn;
RgnHandle tempRgn;
SetPt(&corner, titleRect.left, titleRect.top);
LocalToGlobal(&corner);
// Choose correct pattern, depending on position of window in global
// coordinates. (Concept of new (2.3) version taken from _Macintosh
// Programming Secrets_, Second Edition, by Scott Knaster and Keith
// Rollin, page 423.)
patternSeed = 0x00550055;
if (!(corner.h & 1))
patternSeed <<= 1;
if (!(corner.v & 1))
patternSeed <<= 8;
*((long*)&titlePat + 1) = *(long*)&titlePat = patternSeed;
// Draw the pattern into the titlebar, but only the areas needed
// (i.e. don't draw into close, zoom boxes)
titleRgn = NewRgn();
tempRgn = NewRgn();
RectRgn(titleRgn, &titleRect);
InsetRgn(titleRgn, 1, 1);
if (window->goAwayFlag) {
GetCloseBox(window, &titleRect, &tempRect);
RectRgn(tempRgn, &tempRect);
DiffRgn(titleRgn, tempRgn, titleRgn);
}
if (window->spareFlag) {
GetZoomBox(window, &titleRect, &tempRect);
RectRgn(tempRgn, &tempRect);
DiffRgn(titleRgn, tempRgn, titleRgn);
}
FillRgn(titleRgn, (ConstPatternParam)&titlePat);
DisposeRgn(titleRgn);
DisposeRgn(tempRgn);
// -- used to be done this way, which would still work, but the new way
// prevents a (barely noticeable) flash of the gadgets
// InsetRect(&titleRect, 1, 1);
// FillRect(&titleRect, &titlePat);
}
//-----------------------------------------------------------------------------
void DrawTitlePat( WindowPeek window, short variation, Rect *titleRect ) {
RGBColor theColor;
switch (variation) {
case blackandwhite:
ForeColor(blackColor);
BackColor(whiteColor);
break;
case sys6color:
SetWctbColor(window, wHiliteColor);
GetWctbColor(window, wTitleBarColor, &theColor);
RGBBackColor(&theColor);
break;
case sys7color:
AvgWctbColor(window, wHiliteColorLight, wHiliteColorDark,
wTitleBarLightPct, &theColor);
RGBBackColor(&theColor);
AvgWctbColor(window, wHiliteColorLight, wHiliteColorDark,
wTitleBarDarkPct, &theColor);
RGBForeColor(&theColor);
break;
}
DrawTitlePatPat(window, *titleRect);
}
//*****************************************************************************
// CheckDisplay -- Check to see if we are using color title bars
//-----------------------------------------------------------------------------
Boolean CheckAvailable( WindowPeek window, short light, short dark,
short count, short *ramp ) {
// Given a light and dark index value, a count, and and an array of
// 'percentage' values (0x0 to 0xF, or 0 to 15), see if each of the
// values in the ramp maps to a different color on the screen. If not,
// we need to use black-and-white.
RGBColor theColor;
short i;
short result = true;
short colorIndex = -1;
short lastIndex;
for (i = 0 ; i < count && result == true ; i++) {
AvgWctbColor(window, light, dark, ramp[i], &theColor);
lastIndex = colorIndex;
colorIndex = Color2Index(&theColor);
if (i > 0 && colorIndex == lastIndex)
result = false;
}
return result;
}
//-----------------------------------------------------------------------------
short CheckDisplay( short theDepth, short deviceFlags,
GDHandle targetDevice, WindowPeek window ) {
Boolean inColor;
short result;
RGBColor testColor;
GDHandle saveDevice;
inColor = WindData.hasCQD && (deviceFlags & (0x0001 << gdDevType));
result = blackandwhite; // assume Black and White
if (theDepth >= 4) {
if (!WindData.isSystem7) {
result = sys6color; // System 6.0.x Color
} else {
GetWctbColor(window, wTingeLight, &testColor);
if (testColor.red != 0 || testColor.green != 0 || testColor.blue != 0)
// check for B&W control panel setting, otherwise:
result = sys7color; // System 7.0 Color
}
}
// Note: Since I didn't find another way to see if the user had changed
// the settings in the Color control panel to the Black-and-white setting,
// I actually check to see if the rgb components of the light tinge color
// are non-zero (which seemed to be the case with that setting).
if (result == sys7color && inColor && theDepth <= 8) {
short list[5] = { 0x00, 0x07, 0x08, 0x0A, 0x0D };
// Make sure this array is allcated big enough for the largest ramp.
result = blackandwhite;
saveDevice = GetGDevice();
SetGDevice(targetDevice);
if (CheckAvailable(window, wHiliteColorLight, wHiliteColorDark, 5, list)) {
list[0] = 0x00;
list[1] = 0x01;
list[2] = 0x04;
if (CheckAvailable(window, wTitleBarLight, wTitleBarDark, 3, list)) {
list[0] = 0x00;
list[1] = 0x04;
list[2] = 0x0F;
if (CheckAvailable(window, wTingeLight, wTingeDark, 3, list))
result = sys7color;
}
}
SetGDevice(saveDevice);
}
// This part checks to see if there are 'enough' colors to draw the
// title bar in color under System 7. It is supposed to do so in the
// same way that Apple's system WDEF does. I essentially took the
// assembly code that Apple released and tried to make this use the
// same algorithm. Note: the values in list for the first CheckAvailable
// call are set up in the variable declaration in the top of the routine.
// Don't you just LOVE what C lets you do?
return result;
}
//*****************************************************************************
// Windoid drawing loop
//-----------------------------------------------------------------------------
// This information is used to communicate with DeviceLoop callback routine.
typedef struct WDLDataRec {
WindowPeek wdlWindow;
long wdlParam;
} WDLDataRec;
//-----------------------------------------------------------------------------
// This routine actually does the real work of the drawing of stuff into
// the window.
pascal void WindoidDrawLoop( short depth, short deviceFlags,
GDHandle targetDevice, WDLDataRec *userData ) {
#pragma unused(targetDevice)
Rect titleRect;
Rect tempRect;
RGBColor theColor;
WindowPeek window;
short fancy;
window = userData->wdlWindow;
fancy = CheckDisplay(depth, deviceFlags, targetDevice, window);
if (window->visible)
switch (userData->wdlParam) {
case wNoHit:
BackColor(whiteColor);
// Draw titlebar
if (WindData.hasTitlebar) {
GetTitleBar(window, &titleRect);
switch (fancy) {
case blackandwhite:
ForeColor(blackColor);
break;
case sys6color:
SetWctbColor(window, wFrameColor);
break;
case sys7color:
if (WindData.ignoreHilite || window->hilited)
SetWctbColor(window, wFrameColor);
else {
AvgWctbColor(window, wHiliteColorLight, wHiliteColorDark,
wInactiveFramePct, &theColor);
RGBForeColor(&theColor);
}
break;
}
FrameRect(&titleRect);
}
if (WindData.ignoreHilite || window->hilited) {
if (WindData.hasTitlebar)
DrawTitlePat(window, fancy, &titleRect);
// Draw close box
if (window->goAwayFlag) {
GetCloseBox(window, &titleRect, &tempRect);
DrawCloseBox(window, fancy, &tempRect);
}
// Note: I have seen at least one windoid WDEF that is used
// by some applications that does not utilize this flag.
// In that case, I think it always had a close box (or it
// might even have used the varcode to determine this, but
// that wouldn't seem to be a good thing to do). Anyway, if
// you always want the close box, just comment out the 'if'
// line (and the close brace line) above.
#ifdef ALLOW_ZOOM
// Draw zoom box
if (window->spareFlag) {
GetZoomBox(window, &titleRect, &tempRect);
DrawZoomBox(window, fancy, &tempRect);
}
#endif
} else {
tempRect = titleRect; // dimmed titlebar
InsetRect(&tempRect,1,1);
EraseRect(&tempRect);
}
// Draw content frame and shadow
tempRect = (**(window->strucRgn)).rgnBBox;
tempRect.bottom--;
tempRect.right--;
switch (fancy) {
case blackandwhite:
ForeColor(blackColor);
break;
case sys6color:
SetWctbColor(window, wFrameColor);
break;
case sys7color:
// If the window is not hilited, will use a gray shade
// to draw the window outline in System 7 color.
if (WindData.ignoreHilite || window->hilited)
SetWctbColor(window, wFrameColor);
else {
AvgWctbColor(window, wHiliteColorLight, wHiliteColorDark,
wInactiveFramePct, &theColor);
RGBForeColor(&theColor);
}
break;
}
FrameRect(&tempRect);
ForeColor(blackColor); // draw shadow
MoveTo(tempRect.right, tempRect.top+1);
LineTo(tempRect.right, tempRect.bottom);
LineTo(tempRect.left + 1, tempRect.bottom);
break;
case wInGoAway: // toggle go-away
GetTitleBar(window, &titleRect);
GetCloseBox(window, &titleRect, &tempRect);
if (WindData.closeToggle)
DrawCloseBox(window, fancy, &tempRect);
else
DrawXedBox(window, fancy, &tempRect);
break;
#ifdef ALLOW_ZOOM
default:
if (window->spareFlag) { // toggle zoom box
GetTitleBar(window, &titleRect);
GetZoomBox(window, &titleRect, &tempRect);
if (WindData.zoomToggle)
DrawZoomBox(window, fancy, &tempRect);
else
DrawXedBox(window, fancy, &tempRect);
}
#endif
}
ForeColor(blackColor);
BackColor(whiteColor);
}
//-----------------------------------------------------------------------------
void DoWDraw( WindowPeek window, long param ) {
WDLDataRec theUserData;
GrafPtr savePort;
RgnHandle drawRgn;
Rect theRect;
GDHandle theDevice;
short inColor;
GetPort(&savePort);
SetPort((GrafPtr)window);
drawRgn = window->strucRgn;
SetPort(savePort);
theUserData.wdlWindow = window;
theUserData.wdlParam = param;
if (WindData.isSystem7) {
DeviceLoop(drawRgn, (DeviceLoopDrawingProcPtr)WindoidDrawLoop,
(long)&theUserData, (DeviceLoopFlags)0);
} else {
inColor = 0;
if (window && WindData.hasCQD) {
GetGlobalContentRect(window, &theRect);
theDevice = GetMaxDevice(&theRect);
if (theDevice)
WindoidDrawLoop((**(**theDevice).gdPMap).pixelSize, // <-- depth
(**theDevice).gdFlags,
theDevice, &theUserData);
else
WindoidDrawLoop(1, 0, nil, &theUserData);
// Do this for pre-System 7. we call WindoidDrawLoop directly, giving
// it the information on the device with maximum depth, hoping that
// the results will be okay. Only reason it might not be is if you
// have a System 6 color window that crosses two monitors that have
// differing environments where one doesn't have enough colors to
// show the color version. Here, the problem will be only cosmetic,
// though. Note: I could have done my own device loop for this case,
// but I figured it wasn't common enough for the expense.
} else {
WindoidDrawLoop(1, 0, nil, &theUserData);
// Do this for 68000's
}
}
if (window->visible) {
switch (param) {
case 0:
// This is so param 0 doesn't get interpreted as a hit in the
// zoom box, incorrectly.
break;
case wInGoAway: // toggle go-away
WindData.closeToggle = !(WindData.closeToggle);
break;
#ifdef ALLOW_ZOOM
default: // toggle zoom box
WindData.zoomToggle = !(WindData.zoomToggle);
break;
#endif
}
}
ForeColor(blackColor);
BackColor(whiteColor);
}
//*****************************************************************************
// DoWCalcRgns -- Windoid region calculating routine
//-----------------------------------------------------------------------------
void DoWCalcRgns( WindowPeek window, long param ) {
#pragma unused(param)
Rect contentRect;
Rect structRect;
RgnHandle tempRgn;
GrafPtr savePort;
GetPort(&savePort);
SetPort((GrafPtr)window);
contentRect = window->port.portRect;
OffsetRect(&contentRect, -window->port.portBits.bounds.left,
-window->port.portBits.bounds.top);
RectRgn(window->contRgn, &contentRect);
// start off with the structure equal to the content
structRect = contentRect;
// make it include the window frame and titlebar
InsetRect(&structRect, -1, -1);
if (WindData.hasTitlebar) {
if (WindData.isHoriz)
structRect.top -= kTitleHeight - 1;
else
structRect.left -= kTitleHeight - 1;
}
RectRgn(window->strucRgn, &structRect);
// add the shadow to the structure
OffsetRect(&structRect, 1, 1);
tempRgn = NewRgn();
RectRgn(tempRgn, &structRect);
UnionRgn(tempRgn, window->strucRgn, window->strucRgn);
DisposeRgn(tempRgn);
SetPort(savePort);
}
//*****************************************************************************
// DoWGrow -- Windoid region calculating routine
//-----------------------------------------------------------------------------
// I don't allow of a grow box in a windoid. If you want one, you will
// have to implement these two routines.
void DoWGrow( WindowPeek window, long param ) {
#pragma unused(window, param)
}
//*****************************************************************************
// DoWDrawGIcon -- Draw the grow icon in the lower right corner
//-----------------------------------------------------------------------------
void DoWDrawGIcon( WindowPeek window, long param ) {
#pragma unused(window, param)
}
//*****************************************************************************